# -*- coding: utf-8 -*-
# Copyright (C) 2025 浮浪菌 https://bt23.tv/ZgxoBKO
# 本程序遵循 GPL-3.0 及附加条款：禁止商业使用、禁止修改。

"""
微信素材上传脚本（带 token 缓存）
"""

import json
import os
import sys
import time
import requests

# ------------------ 默认配置 ------------------
DEFAULT_CFG = {
    "AppID": "填写你的 AppID",
    "AppSecret": "填写你的 AppSecret"
}

# 无论脚本还是打包 exe，配置/缓存都放在“exe 或脚本所在目录”
if getattr(sys, 'frozen', False):
    BASE_DIR = os.path.dirname(sys.executable)
else:
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    
CFG_FILE = os.path.join(BASE_DIR, 'config.json')
TOK_FILE = os.path.join(BASE_DIR, 'token.json')

def load_cfg():
    """读取或创建 config.json"""
    if not os.path.isfile(CFG_FILE):
        with open(CFG_FILE, 'w', encoding='utf-8') as f:
            json.dump(DEFAULT_CFG, f, indent=4, ensure_ascii=False)
        print(f'已生成配置文件：{CFG_FILE}')
        print('请先修改其中的 AppID 和 AppSecret，再重新运行！')
        sys.exit(0)

    with open(CFG_FILE, 'r', encoding='utf-8') as f:
        cfg = json.load(f)
    return cfg['AppID'], cfg['AppSecret']

def get_access_token(appid, secret):
    """带缓存的 access_token 获取，并在报错时打印本机公网 IP"""
    import socket
    now = int(time.time())

    # 读缓存
    if os.path.isfile(TOK_FILE):
        try:
            with open(TOK_FILE, 'r', encoding='utf-8') as f:
                cache = json.load(f)
            token, fetch_time = cache.get('access_token'), cache.get('fetch_time', 0)
            if now - fetch_time < 7000:
                return token
        except Exception:
            pass

    try:
        my_ip = requests.get('https://api.ipify.org', timeout=3).text.strip()
    except Exception:
        my_ip = '无法获取'

    url = (
        "https://api.weixin.qq.com/cgi-bin/token"
        f"?grant_type=client_credential&appid={appid}&secret={secret}"
    )
    try:
        resp = requests.get(url, timeout=10)
        resp.raise_for_status()
        data = resp.json()
    except Exception as e:
        print("网络错误：", e)
        print("当前公网 IP：", my_ip)
        sys.exit(1)

    if 'access_token' not in data:
        print("微信返回错误：", data)
        print("当前公网 IP：", my_ip)
        print("若 errcode=40164，请把上方 IP 加入公众号后台【IP 白名单】后再试！")
        sys.exit(1)

    access_token = data['access_token']
    with open(TOK_FILE, 'w', encoding='utf-8') as f:
        json.dump({'access_token': access_token, 'fetch_time': now}, f, indent=2)
    return access_token

def upload_images(access_token, paths):
    upload_url = (
        f"https://api.weixin.qq.com/cgi-bin/media/uploadimg"
        f"?access_token={access_token}&type=image"
    )
    urls = []
    for p in paths:
        if not os.path.isfile(p):
            print(f"文件不存在：{p}")
            continue
        try:
            with open(p, 'rb') as f:
                files = {'media': (os.path.basename(p), f, 'image/png')}
                resp = requests.post(upload_url, files=files, timeout=30)
                resp.raise_for_status()
                result = resp.json()
                url = result.get('url')
                if url:
                    urls.append(url)
                else:
                    print(f"上传失败：{result}")
        except Exception as e:
            print(f"上传 {p} 出错：{e}")
    return urls

def main():
    if len(sys.argv) < 2:
        print("请拖拽图片到脚本/EXE 上，或在命令行传入图片路径。")
        sys.exit(0)

    appid, secret = load_cfg()
    access_token = get_access_token(appid, secret)
    urls = upload_images(access_token, sys.argv[1:])

    if urls:
        print("Upload Success:")
        for u in urls:
            print(u)

if __name__ == '__main__':
    main()